﻿/// <reference path="jquery.js" />        
/*jslint browser: true */
/*globals $:false, System:false, window:false*/

Date.prototype.addMonths = function (months) {
  var date = new Date(this.getTime());
  date.setMonth(this.getMonth() + months);
  return date;
};

Date.prototype.isToday = function () {
  var today = new Date();
  return (this.getDate() === today.getDate() &&
          this.getMonth() === today.getMonth() &&
          this.getFullYear() === today.getFullYear());
};

var APP = {};
APP.UTILITY = {};

APP.UTILITY.setting = function (name, defaultValue) {
  return function (value) {
    if (value !== undefined) {
      System.Gadget.Settings.write(name, value);
    }
    else {
      var setting = System.Gadget.Settings.read(name);
      return (setting !== "") ? setting : defaultValue;
    }
  };
};

APP.UTILITY.property = function (property, event) {
  return function (value) {
    if (value !== undefined) {
      if (value !== property) {
        property = value;
        if (event) { $("#calendar").trigger(event); }
      }
    }
    else { return property; }
  };
};

APP.UTILITY.alert = function (message) {
  var shell = new ActiveXObject("WScript.Shell");
  shell.Popup(message);
};

APP.UTILITY.navigateTo = function (link) {
  var shell = new ActiveXObject("WScript.Shell");
  shell.Run(link);
};
 
APP.calendar = function () {
  var that = {};

  var sizeMonth = { width: 130, height: 127 };
  var days = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
  var months = ["January", "February", "March", "April", "May", "June",
                "July", "August", "September", "October", "November", "December"];

  that.width = function (cols) { return cols * sizeMonth.width; };
  that.height = function (rows) { return rows * sizeMonth.height; };

  that.generateDay = function (year, month, day, last, hasToday) {
    var show = day >= 1 && day <= last;
    var cell = $("<td>", { html: show ? day : "&nbsp;" });
    if (hasToday && show && new Date(year, month, day).isToday()) { cell.addClass("today"); }
    return cell;
  };

  that.generateWeek = function (year, month, day, last, hasToday) {
    var row = $("<tr>");
    var end = day + 7;
    for (var d = day; d < end; d += 1) { row.append(that.generateDay(year, month, d, last, hasToday)); }
    return row;
  };

  that.generateMonth = function (date) {
    var month = $("<div>", { "class": "month" });
    month.append($("<div>", { text: months[date.getMonth()] + " " + date.getFullYear() }));

    var daysRow = $("<tr>");
    $.each(days, function () { daysRow.append($("<th>", { text: this.toString() })); });
    var table = $("<table>").append(daysRow);

    var first = (new Date(date.getFullYear(), date.getMonth(), 1).getDay() - 1) * -1;
    var last = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
    var today = new Date();
    var hasToday = today.getFullYear() === date.getFullYear() && today.getMonth() === date.getMonth();
    var weeksInMonth = 6;
    var daysInWeek = 7;

    for (var i = 0; i < weeksInMonth; i += 1) {
      table.append(that.generateWeek(date.getFullYear(), date.getMonth(), first, last, hasToday));
      first += daysInWeek;
    }
    return month.append(table, $("<hr/>"));
  };

  that.generate = function (start, months) {
    var cal = $("<div>");
    for (var i = 0; i < months; i += 1) {
      cal.append(that.generateMonth(start.addMonths(i)));
    }
    return cal;
  };

  return that;
};

APP.settings = {
  dockedRows: APP.UTILITY.setting("dockedRows", 3),
  dockedCols: APP.UTILITY.setting("dockedCols", 1),
  undockedRows: APP.UTILITY.setting("undockedRows", 3),
  undockedCols: APP.UTILITY.setting("undockedCols", 4)
};

APP.model = function () {
  var that = {};
  var dockedSize = { rows: APP.settings.dockedRows(), cols: APP.settings.dockedCols() };
  var undockedSize = { rows: APP.settings.undockedRows(), cols: APP.settings.undockedCols() };

  that.dockedSize = APP.UTILITY.property(dockedSize, "sizeChanged");
  that.undockedSize = APP.UTILITY.property(undockedSize, "sizeChanged");
  that.today = APP.UTILITY.property(new Date(), "todayChanged");
  that.startDate = APP.UTILITY.property(new Date(), "startDateChanged");

  return that;
};

APP.view = function (model) {
  var that = {};
  var calendar = APP.calendar();

  var size = function () {
    return (System.Gadget.docked) ? model.dockedSize() : model.undockedSize();
  };

  that.changeSize = function () {
    var width = calendar.width(size().cols);
    var height = calendar.height(size().rows);
    $(document.body, "#border").css({ "width": width, "height": height });
    that.generateCalendar();
  };

  that.generateCalendar = function () {
    var cal = calendar.generate(model.startDate(), size().rows * size().cols);
    $("#content").empty().append(cal.attr("id", "calendar"));
  };

  that.showEvent = function (event) {
    debugger;
    APP.events = event;
    System.Gadget.Flyout.show = true;
  };

  $("#calendar").live("sizeChanged", that.changeSize);
  $("#calendar").live("startDateChanged todayChanged", that.generateCalendar);
  System.Gadget.onDock = System.Gadget.onUndock = that.changeSize;

  return that;
};

APP.controller = function (model, view) {
  var that = {};

  document.onmousewheel = function () {
    var scroll = (window.event.wheelDelta < 0) ? 1 : -1;
    model.startDate(model.startDate().addMonths(scroll));
  };

  $("td").live("mousedown", function () {
    var text = $(this).text();
    if (+text) { view.showEvent(text); }
  });

  var minute = 60000;

  setInterval(function () {
    var today = new Date();
    if (!model.today().isToday()) { model.today(new Date()); }
  },
  minute);

  System.Gadget.onSettingsClosed = function (e) {
    if (e.closeAction === e.Action.commit) {
      model.dockedSize({ rows: APP.settings.dockedRows(), cols: APP.settings.dockedCols() });
      model.undockedSize({ rows: APP.settings.undockedRows(), cols: APP.settings.undockedCols() });
    }
  };

  return that;
};

APP.run = function () {
  System.Gadget.settingsUI = "settings.html";
  System.Gadget.Flyout.file = "events.html";

  var model = APP.model();
  var view = APP.view(model);
  APP.controller(model, view);
  view.changeSize();
};